/*******************************************************************************
 * Copyright (c) 2011 Grupo de Sistemas Inteligentes (GSI) - DIT UPM
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *******************************************************************************/
package es.upm.dit.gsi.eclipse.jadex.adfmanager.wizards;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Spinner;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Button;

/**
 * This page allows to get the following information:
 *  - Parameter list
 *  
 *  @author Pablo Muñoz
 *  @TODO parameterset support, hide the advanced parameter with a bar
 *  
 */

public class ParameterSelectionWizardPage extends WizardPage {
	//Basic options
	private Text nameText;
	private Text classText;
	private Text valueText;
	private Text descriptionText;
	
	//Advanced options
	//ExpandBar advancedBar;
	
	private Combo directionCombo;
	private Combo dynamicCombo;
	private Combo exportedCombo;
	private Combo optionalCombo;
	private Combo transientCombo;
	private Spinner updateRateSpinner;
	
	private Button addButton;
	private Button deleteButton;
	
	private Table paramTable;
	
	
	/**
	 * Constructor for AddGoalWizardPage3
	 * 
	 * @param pageName
	 */
	public ParameterSelectionWizardPage(ISelection selection) {
		super("wizardPage");
		setDescription("Page 3: parameters");
	}


	

	/**
	 * @see IDialogPage#createControl(Composite)
	 */
	public void createControl(Composite parent) {
		Composite container = new Composite(parent, SWT.NULL);
		GridLayout layout = new GridLayout();
		container.setLayout(layout);
		layout.numColumns = 4;
		layout.horizontalSpacing = 9;
		layout.verticalSpacing = 9;		
		
		Label label1 = new Label(container, SWT.NULL);
		label1.setText("Name: ");
		nameText = new Text(container, SWT.BORDER | SWT.SINGLE);
		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
		nameText.setLayoutData(gd);
		nameText.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				dialogChanged();
			}
		});
		
		Label label2 = new Label(container, SWT.NULL);
		label2.setText("Class: ");
		classText = new Text(container, SWT.BORDER | SWT.SINGLE);
		gd = new GridData(GridData.FILL_HORIZONTAL);
		classText.setLayoutData(gd);
		classText.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				dialogChanged();
			}
		});
		
		Label label3 = new Label(container, SWT.NULL);
		label3.setText("Value: ");
		valueText = new Text(container, SWT.BORDER | SWT.SINGLE);
		gd = new GridData(GridData.FILL_HORIZONTAL);
		valueText.setLayoutData(gd);
		valueText.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				dialogChanged();
			}
		});
		
		Label label4 = new Label(container, SWT.NULL);
		label4.setText("Description: ");
		descriptionText = new Text(container, SWT.BORDER | SWT.SINGLE);
		gd = new GridData(GridData.FILL_HORIZONTAL);
		descriptionText.setLayoutData(gd);
		descriptionText.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				dialogChanged();
			}
		});
		
		Label separator = new Label(container, SWT.SEPARATOR | SWT.HORIZONTAL);
		gd = new GridData(GridData.FILL_HORIZONTAL);
		separator.setLayoutData(gd);
		gd.horizontalSpan = 4;
		
		Label label6 = new Label(container, SWT.NULL);
		label6.setText("Direction: ");
		directionCombo = new Combo(container, SWT.READ_ONLY);
		directionCombo.setItems(new String[]{"in","out","inout","fixed"});
		directionCombo.select(0);
		gd = new GridData(GridData.FILL_HORIZONTAL);
		directionCombo.setLayoutData(gd);
		directionCombo.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				dialogChanged();
			}
		});		
		
		Label label7 = new Label(container, SWT.NULL);
		label7.setText("Dynamic: ");
		dynamicCombo = new Combo(container, SWT.READ_ONLY);
		dynamicCombo.setItems(new String[]{"true","false"});
		dynamicCombo.select(1);
		gd = new GridData(GridData.FILL_HORIZONTAL);
		dynamicCombo.setLayoutData(gd);
		dynamicCombo.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				dialogChanged();
			}
		});
		
		Label label8 = new Label(container, SWT.NULL);
		label8.setText("Exported: ");
		exportedCombo = new Combo(container, SWT.READ_ONLY);
		exportedCombo.setItems(new String[]{"true","false","shielded"});
		exportedCombo.select(1);
		gd = new GridData(GridData.FILL_HORIZONTAL);
		exportedCombo.setLayoutData(gd);
		exportedCombo.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				dialogChanged();
			}
		});
		
		Label label9 = new Label(container, SWT.NULL);
		label9.setText("Optional: ");
		optionalCombo = new Combo(container, SWT.READ_ONLY);
		optionalCombo.setItems(new String[]{"true","false"});
		optionalCombo.select(1);
		gd = new GridData(GridData.FILL_HORIZONTAL);
		optionalCombo.setLayoutData(gd);
		optionalCombo.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				dialogChanged();
			}
		});
		
		Label label10 = new Label(container, SWT.NULL);
		label10.setText("Transient: ");
		transientCombo = new Combo(container, SWT.READ_ONLY);
		transientCombo.setItems(new String[]{"true","false"});
		transientCombo.select(1);
		gd = new GridData(GridData.FILL_HORIZONTAL);
		transientCombo.setLayoutData(gd);
		transientCombo.addModifyListener(new ModifyListener() {
			@Override
			public void modifyText(ModifyEvent e){ 
				dialogChanged();				
			}
		});
		
		Label label11 = new Label(container, SWT.NULL);
		label11.setText("&Priority (optional):");
		gd = new GridData(GridData.FILL_HORIZONTAL);
		updateRateSpinner = new Spinner (container, SWT.BORDER);
		updateRateSpinner.setIncrement(1);
		updateRateSpinner.setPageIncrement(1);
		updateRateSpinner.setSelection(0);
		updateRateSpinner.setLayoutData(gd);
		updateRateSpinner.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				dialogChanged();
			}
		});
		
		addButton = new Button(container,SWT.PUSH);
		addButton.setText("Add");
		gd = new GridData(GridData.FILL_HORIZONTAL);
		gd.horizontalSpan = 2;
		addButton.setLayoutData(gd);
		addButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				if(paramTable.getSelection().length > 0){
					addButtonPushed(true);
				}
				else{
					addButtonPushed(false);
				}
			}
		});
		
		deleteButton = new Button(container,SWT.PUSH);
		deleteButton.setText("Delete");
		gd = new GridData(GridData.FILL_HORIZONTAL);
		gd.horizontalSpan = 2;
		deleteButton.setLayoutData(gd);
		deleteButton.setEnabled(false);
		deleteButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				deleteButtonPushed();
			}
		});
		
		paramTable = new Table (container, SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION);
		paramTable.setLinesVisible (true);
		paramTable.setHeaderVisible (true);
    	gd = new GridData(GridData.FILL_HORIZONTAL);
		gd.horizontalSpan = 4;
    	gd.heightHint = 200;
    	paramTable.setLayoutData(gd);
    	String[] titles = {"Name", "Class", "Value", "Description", "Direction", "Dynamic", "Exported", "Optional", "Transient", "Update Rate"};
    	for (String s : titles){
    		TableColumn column = new TableColumn (paramTable, SWT.NONE);
    		column.setText(s);
    	}	
    	for(TableColumn t : paramTable.getColumns()){
    		t.pack();    		
    	}
    	paramTable.addSelectionListener(new SelectionListener() {
			
			@Override
			public void widgetSelected(SelectionEvent e) {
				parameterSelected();
			}
			
			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
			}
		});
    	
		initialize();
		dialogChanged();
		setControl(container);
	}

	/*
	 * This method is called when the add button is pushed.
	 * It adds a new parameter or modify an existing one depending on 
	 * the desired operation.
	 */
	private void addButtonPushed(Boolean modify){
		if(modify){
			TableItem item = paramTable.getSelection()[0];
			item.setText(0,nameText.getText());
			item.setText(1,classText.getText());
			item.setText(2,valueText.getText());
			item.setText(3,descriptionText.getText());
			item.setText(4,directionCombo.getText());
			item.setText(5,dynamicCombo.getText());
			item.setText(6,exportedCombo.getText());
			item.setText(7,optionalCombo.getText());
			item.setText(8,transientCombo.getText());
			item.setText(9,updateRateSpinner.getSelection() + "");
		}
		else{
			Parameter p = new Parameter(nameText.getText(),
					descriptionText.getText(),
					valueText.getText(),
					descriptionText.getText(),
					directionCombo.getText(),
					dynamicCombo.getText(),
					exportedCombo.getText(),
					optionalCombo.getText(),
					transientCombo.getText(),
					updateRateSpinner.getSelection()+"");
			addParameter(p);				
		}
		clearForm();
	}
	
	/*
	 * This method is called when the delete button is pushed
	 */
	private void deleteButtonPushed(){
		paramTable.remove(paramTable.getSelectionIndices());
		clearForm();
	}
	
	/*
	 * This method is called when a parameter is selected in the table
	 */
	private void parameterSelected(){
		TableItem item = paramTable.getSelection()[0];
		nameText.setText(item.getText(0));
		classText.setText(item.getText(1));
		valueText.setText(item.getText(2));
		descriptionText.setText(item.getText(3));
		directionCombo.setText(item.getText(4));
		dynamicCombo.setText(item.getText(5));
		exportedCombo.setText(item.getText(6));
		optionalCombo.setText(item.getText(7));
		transientCombo.setText(item.getText(8));
		updateRateSpinner.setSelection(Integer.parseInt(item.getText(9)));
		deleteButton.setEnabled(true);
		addButton.setText("Modify");
	}
	
	/*
	 * This method is called in order to add a new parameter to the table
	 */
	private void addParameter(Parameter p){
		TableItem item  = new TableItem(paramTable, SWT.NONE);
		item.setText(p.getText());
	}
	
	/*
	 * This method is called in order to generate a new Parameter object
	 * from a table column
	 */
	private Parameter getParameter(TableItem item){
		String[] content = new String[paramTable.getColumnCount()];
		for(int i = 0; i < paramTable.getColumnCount(); i++){
			content[i] = item.getText(i);
		}
		if(content.length > 0){
			return new Parameter(content);
		}
		return null;
	}
	
	/*
	 * This method clears all the controls text
	 */
	private void clearForm(){
		nameText.setText("");
		classText.setText("");
		valueText.setText("");
		descriptionText.setText("");
		directionCombo.setText("in");
		dynamicCombo.setText("false");
		exportedCombo.setText("false");
		optionalCombo.setText("false");
		transientCombo.setText("false");
		updateRateSpinner.setSelection(0);
		paramTable.deselectAll();
		addButton.setText("Add");
		deleteButton.setEnabled(false);
	}

	/*
	 * This method is called when the text of any control changes
	 * or set them to the default selection
	 */
	private void dialogChanged() {
		updateStatus(null);
	}
	
	/*
	 * This method is called in order to update the status message 
	 */
	private void updateStatus(String message) {
		setErrorMessage(message);
		setPageComplete(message == null);
	}	
	
	/*
	 * This method is called in order to initialize the controls status
	 */
	private void initialize() {
	}
	
	/**
	 * 
	 * @return an array of parameters
	 */
	public Parameter[] getParameters(){
		List<Parameter> list = new ArrayList<Parameter>();
		for (TableItem item : paramTable.getItems()){
			list.add(getParameter(item));
		}
		return list.toArray(new Parameter[list.size()]);		
	}
}